package mole.state 
{
	import mole.entities.CBackground;
	import mole.entities.CFloor;
	import mole.entities.characters.CMole;
	import mole.entities.CLassie;
	import mole.entities.controlers.CPlayerControler;
	import mole.entities.controlers.CPlayerControler2;
	import mole.entities.controlers.CPlayerControler3;
	import mole.entities.controlers.CPlayerControler4;
	import mole.entities.CPlayer;
	import mole.entities.CTileMap;
	import mole.entities.decors.CDecor;
	import mole.entities.triggers.CDoor;
	import mole.Main;
	import net.flashpunk.utils.Input;
	import net.flashpunk.utils.Key;
	import net.flashpunk.FP;
	import mole.entities.particles.CParticleEmitter;
	
	/**
	 * ...
	 * @author Cédric Liaudet
	 */
	public class CInGame implements IState
	{
		[Embed(source = '../../data/sounds/music_ingame.mp3')]
		private const MUSIC:Class;
		
		/**
		 * Constructeur par défaut.
		 */
		public function CInGame() 
		{
			Input.define("pause", Key.ENTER);
			
			m_aLiquids = new Array;
			m_aBackground = new Array;
			m_aWalls = new Array;
			m_aTilemap = new Array;
			m_aFloors = new Array;
			m_AddParticle = 0;
			m_nDifficulty = 0;
			m_fNextDifficulty = 30.0;
		}
		
		/**
		 * Chargement des données.
		 */
		public function OnStart():void
		{
			m_bImpossible = false;
			Main.SoundManager.PlayMusic(MUSIC, true, 2);			
			
			// chargement de la map.
			Main.World.LoadLevel("data/level_0.xml", OnReady);
			
			m_nSpeed = 10;
			
			// chargement du liquide.
			var width:int = 0;
			while (width < (1024 + 256))
			{
				var decor:CDecor = new CDecor(0, width, 512 - 96);
				decor.layer = 0;
				width += decor.width;
				Main.World.add(decor);
				m_aLiquids.push(decor);
			}
			
			var i:int = 0;
			// chargement des backgrounds.
			for(i = 0; i < 3; i++)
			{
				// 2 background par type.
				var background_0:CBackground = new CBackground(i, i);
				background_0.x = 0;
				var background_1:CBackground = new CBackground(i, i);
				background_1.x = 1024;
				
				// herbe
				if (i == 2)
				{
					background_0.y = background_1.y = 128;
				}
				
				Main.World.add(background_0);
				Main.World.add(background_1);
				m_aBackground.push(background_0);
				m_aBackground.push(background_1);
			}
			
			// chargement des murs
			for (i = 0; i < 7; i++)
			{
				var wall:CBackground  = new CBackground(3, -1);
				Main.World.add(wall);
				m_aWalls.push(wall);
				
				wall.x = i * 192;
				wall.y = 192;
			}
			
			// chargement du sol
			for (i = 0; i < 2; i++)
			{
				var floor:CFloor = new CFloor();
				floor.x = 1024 * i;
				floor.y = 384;
				Main.World.add(floor);
				m_aFloors.push(floor);
			}
			
			
			// placement des joueurs
			for (i = 0; i < Main.GameRules.NbPlayers; i++)			
			{
				var player:CPlayer = Main.GameRules.GetPlayer(i);
				player.x = 512 + (32  * i);
				player.y = 300;			
				Main.World.add(player);
				player.Init();
				player = null;
			}
			
			m_Perforator = new CLassie;
			Main.World.add(m_Perforator);
		}
		
		public function OnReady():void
		{
			m_aTilemap[0] = Main.World.CreateTilemap(0, 1024, false);
			m_aTilemap[1] = Main.World.CreateTilemap(0, 2048, false);
			
			// placement des joueurs
			for (var i:int = 0; i < Main.GameRules.NbPlayers; i++)			
			{
				var player:CPlayer = Main.GameRules.GetPlayer(i);
				player.OnRight();
			}
		}
		
		/**
		 * Mise à jours de l'état.
		 */
		public function OnUpdate(): void
		{
			if (m_aTilemap.length == 0)
				return;
				
			if (Input.pressed("pause"))
			{
				Main.GameStateManager.SetCurrentState(new CPause, false);
			}
			
			// MAJ du liquide.
			var i:int = 0;
			m_aLiquids[0].x -= m_nSpeed;
			if (m_aLiquids[0].x < -(m_aLiquids[0].width))
			{
				m_aLiquids[0].x = 1024;
				var tmpLiquid:CDecor = m_aLiquids[0];
				for (i = 0; i < m_aLiquids.length; i++)
				{
					m_aLiquids[i] = m_aLiquids[i + 1];
				}
				
				m_aLiquids[m_aLiquids.length - 1] = tmpLiquid;
			}
			
			var posX:int = m_aLiquids[0].x;
			for (i = 1; i < m_aLiquids.length; i++)
			{				
				m_aLiquids[i].x = posX + (m_aLiquids[i].width * i);
			}
			
			// MAJ background.
			for (i = 0; i < 6; i++)
			{
				var background:CBackground = m_aBackground[i];
				
				if (i % 2)
				{
					if (m_aBackground[i - 1].x < background.x)
						background.x = m_aBackground[i - 1].x + 1024;
					else
					{
						background.x = m_aBackground[i - 1].x - 1024;
						if (background.x <= -1024)
							background.x = m_aBackground[i - 1].x + 1024;
					}	
				}
				else
				{
					background.x -= m_nSpeed * ((i + 1) / 5);
					if (background.x <= -1024)
						background.x = 1024 - (1024 + background.x);
				}				
			}
			
			// MAJ walls
			var wall:CBackground = m_aWalls[0];
			wall.x -= m_nSpeed;
			if (wall.x < -192)
			{
				var nWallPosX:int = 192 + wall.x;
				
				Main.World.remove(wall);
					
				m_aWalls.shift();
				wall = new CBackground(3, -1);
				Main.World.add(wall);
				m_aWalls.push(wall);					
					
				wall.y = 192;
				wall.x = m_aWalls[m_aWalls.length - 2].x + 192;
								
				wall = m_aWalls[0];
				wall.x = nWallPosX;
			}
			
			for (i = 1; i < 7; i++)
			{		
				var sub_wall:CBackground = m_aWalls[i];
				sub_wall.x = wall.x + (192 * i);				
			}
			
			// MAJ templates
			var tilemap:CTileMap = m_aTilemap[0];
			tilemap.x -= m_nSpeed;
			if (tilemap.x < -1024)
			{
				var nTilemapPosX:int = 1024 + tilemap.x;									
					
				tilemap.Clear();
				m_aTilemap.shift();
				tilemap = Main.World.CreateTilemap(m_nDifficulty, 1024, m_bImpossible);
				m_aTilemap.push(tilemap);
				m_bImpossible = false;
				m_aTilemap[0].x = nTilemapPosX;
			}
			
			m_aTilemap[1].x = m_aTilemap[0].x + 1024;
			
			// MAJ sol
			var floor:CFloor = m_aFloors[0];
			floor.x -= m_nSpeed;
			if (floor.x < -1024)
			{
				var nFloorPosX:int = 1024 + floor.x;
				
				Main.World.remove(floor);				
				m_aFloors.shift();
				floor = new CFloor;
				floor.x = nFloorPosX + 1024;
				floor.y = 384;
				Main.World.add(floor);
				m_aFloors.push(floor);
				
				m_aFloors[0].x = nFloorPosX;
			}
			m_aFloors[1].x = m_aFloors[0].x + 1024;
			
			// Ajout particules
			m_AddParticle -= FP.elapsed;
			if (m_AddParticle <= 0)
			{
				m_AddParticle = 0.25;
				CParticleEmitter.GenerateParticlesAtPoint(192, 425, 1, 1, 2, 10, -1, 0, -0.8, 0.2, 150, 180, 20);
			}
			
			// placement des joueurs
			var nearVolume:Number = 1024;
			for (i = 0; i < Main.GameRules.NbPlayers; i++)			
			{
				var player:CPlayer = Main.GameRules.GetPlayer(i);
				if (nearVolume >  player.x)
				{
					nearVolume = player.x;
				}
			}
			
			m_Perforator.SetVolume(((m_Perforator.x + 512) - nearVolume) / 288);
			
			m_fNextDifficulty -= FP.elapsed;
			if (m_fNextDifficulty <= 0.0)
			{
				m_fNextDifficulty = 30.0;
				m_nDifficulty++;
				m_bImpossible = true;
			}
		}
		
		/**
		 * "Destruction" des données.
		 */
		public function OnEnd():void
		{
			Main.SoundManager.StopMusic(false);
			
			// suppression de tout les elements graphiques.
			Main.World.removeAll();
			
			m_Perforator.Stop();
			m_Perforator = null;
		}
		
		/**
		 * Mise en pause
		 */
		public function OnPause():void
		{
			Main.World.active = false;
		}
		
		/**
		 * Retour de pause
		 */
		public function OnResume():void
		{
			Main.World.active = true;
		}
		
		private var m_nSpeed:int;
		private var m_aLiquids:Array;
		private var m_aBackground:Array;
		private var m_aWalls:Array;
		private var m_aTilemap:Array;
		private var m_aFloors:Array;
		private var m_Perforator:CLassie;
		private var m_AddParticle:Number;
		private var m_nDifficulty:int;
		private var m_fNextDifficulty:Number;
		private var m_bImpossible:Boolean;
	}

}